
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "upgrade_core.h"
#include "usb_fp_protocol.h"
#include "common.h"
#include "uapi_usb.h"
#include "ofp_config.h"
#include "ofp_dev.h"



ofp_dev *g_ofp_dev;


static ofp_upgrade_firmware* ofp_get_firmware_data(uint8_t *firmware_name)
{
    ofp_upgrade_firmware *firmware = NULL;
    struct stat file_stat;
    FILE *file = NULL;
    int32_t read_size =0;


    OFP_LOGD("ofp_get_firmware_data =====================>enter\n");
    if (firmware_name == NULL) {

        OFP_LOGD("ofp_get_firmware invalid param\n");
        return NULL;
    }

    if (stat(firmware_name, &file_stat) < 0) {
        OFP_LOGE("stat %s failed \n", firmware_name);
        return NULL;
    }

    firmware = (ofp_upgrade_firmware *)calloc(1, sizeof(ofp_upgrade_firmware));
    firmware->firmware_len = file_stat.st_size;
    firmware->firmware_data = (uint8_t *)calloc(1, (firmware->firmware_len * sizeof(uint8_t)));

    file = fopen(firmware_name, "rb");
    if (file  == NULL) {
        OFP_LOGE("open %s failed \n", firmware_name);
        goto OPEN_ERROR;
    }
    read_size = fread(firmware->firmware_data, 1, firmware->firmware_len, file);
    if (read_size != firmware->firmware_len) {
        OFP_LOGE("read %s failed \n", firmware_name);
        goto READ_ERROR;
    }

    fclose(file);

    OFP_LOGD("ofp_get_firmware_data =====================>exit\n");

    return firmware;

READ_ERROR:
    fclose(file);
OPEN_ERROR:
    free(firmware->firmware_data);
    firmware->firmware_data = NULL;
    free(firmware);
    firmware =NULL;
    OFP_LOGD("ofp_get_firmware =====================>error exit\n");
    return NULL;
}

static int32_t ofp_check_upgrade_firmware_version(ofp_dev *dev, ofp_firmware_version fw_ver)
{
    ofp_upgrade_result ret = UPGRADE_NO_NEED;
    ofp_drv_upgrade_param_conf *upc = &(dev->drv_cfg.upgrade_param_conf);
    OFP_LOGD("ofp_check_upgrade_firmware_version:   drv conf firmware_version:%s upgrade_mode:%d \n", \
        upc->firmware_version, upc->upgrade_mode);

    switch (upc->upgrade_mode) {
        case FORCE_UPGRADE:
            ret = UPGRADE_NEED;
            break;
        case DONT_UPGRADE:
            ret = UPGRADE_NO_NEED;
            break;
        case AUTO_UPGRADE:
            if (memcmp(fw_ver.firmware_version, upc->firmware_version, fw_ver.len) != 0) {
                ret = UPGRADE_NEED;
            } else {
                ret = UPGRADE_NO_NEED;
            }
            break;
        case SMART_UPGRADE:
            if (memcmp(fw_ver.firmware_version, upc->firmware_version, fw_ver.len) < 0) {
                ret = UPGRADE_NEED;
            } else {
                ret = UPGRADE_NO_NEED;
            }
            break;
        default:
            ret = UPGRADE_NO_NEED;
            break;
    }

    return ret;
}

static int32_t ofp_usb_prepare_upgrade(ofp_dev *dev)
{
    int ret;
    uint8_t firmware_version[OFP_FIRMWARE_NAME_LEN_MAX] = {0};
    ofp_firmware_version fw_ver = {0};
    uint32_t version_len = 0;
    ofp_drv_device_param_conf *dpc = &(dev->drv_cfg.device_param_conf);
    ofp_drv_upgrade_param_conf *upc = &(dev->drv_cfg.upgrade_param_conf);

    ret = uapi_open_usb_handle_by_vid(dpc->usb_vid, &(dev->usb_handle));
    if (ret < 0) {
        OFP_LOGI("uapi_open_usb_handle_by_vid   vendor_id failed\n");
        uapi_close_usb_handle(&(dev->usb_handle));
        return UPGRADE_FAILURE;
    }

    memset(&fw_ver, 0, sizeof(ofp_firmware_version));
    ret = ofp_usb_get_firmware_version(&(dev->usb_handle), &fw_ver);
    if (ret < 0) {
        OFP_LOGE("ofp_usb_get_firmware_version error\n");
        uapi_close_usb_handle(&(dev->usb_handle));
        return UPGRADE_GET_FIRMWARE_VERSION_FAILURE;
    }
    OFP_LOGI("firmware_version = %s \n", fw_ver.firmware_version);
    ret = ofp_check_upgrade_firmware_version(dev, fw_ver);
    if (ret = UPGRADE_NO_NEED) {
        OFP_LOGE("version check , not upgrade\n");
        uapi_close_usb_handle(&(dev->usb_handle));
        return UPGRADE_NO_NEED;
    }

    ret = ofp_usb_goto_boot(&(dev->usb_handle));
    if (ret < 0) {
        OFP_LOGE("ofp_usb_goto_boot error\n");
        uapi_close_usb_handle(&(dev->usb_handle));
        return UPGRADE_APP_TO_BOOT_FAILURE;
    }
    uapi_close_usb_handle(&(dev->usb_handle));
    sleep(3); //进入boot状态，先等待一段时间

    return UPGRADE_SUCCESS;
}

static int32_t ofp_usb_upgrade(ofp_dev *dev)
{
    ofp_upgrade_firmware *firmware = NULL;
    ofp_drv_device_param_conf *dpc = &(dev->drv_cfg.device_param_conf);
    ofp_drv_upgrade_param_conf *upc = &(dev->drv_cfg.upgrade_param_conf);
    int ret;
    ofp_upgrade_fun mcu_upgrade_fun;

    ret = uapi_usb_init();
    if (ret < 0) {
        OFP_LOGE("upgrade uapi_usb_init error \n");
        return UPGRADE_FAILURE;
    }

    ret = ofp_usb_prepare_upgrade(dev);
    if (ret == UPGRADE_NO_NEED) {
        OFP_LOGE("upgrade ofp_usb_prepare_upgrade error code: %d \n", ret);
        uapi_usb_exit();
        return UPGRADE_SUCCESS;
    }

    firmware = ofp_get_firmware_data(upc->firmware_name);
    if ((firmware == NULL) || (firmware->firmware_data == NULL)) {
        OFP_LOGE("ofp_usb_upgrade ofp_get_firmware_data error\n");
        return UPGRADE_GET_FIRMWARE_FAILURE;
    }


    ret = uapi_open_usb_handle_by_vid(upc->boot_usb_vid, &(dev->usb_boot_handle));
    if (ret < 0) {
        OFP_LOGE("uapi_open_usb_handle_by_vid boot_vendor_id error\n");
        ret = UPGRADE_FAILURE;
        goto MCU_UPGRADE_ERROR;
    }

    mcu_upgrade_fun = g_mcu_drv_info[dpc->mcu_type].mcu_upgrade_fun;

    ret = mcu_upgrade_fun(((void *)(&(dev->usb_boot_handle))), ((void *)(firmware)));
    if (ret < 0) {
        OFP_LOGE("mcu_upgrade_fun error, mcu type: %d \n", dpc->mcu_type);
        ret = UPGRADE_FAILURE;
        goto MCU_UPGRADE_ERROR;

    }

    ret = ofp_dev_set_drv_upgrade_flag(&(dev->drv_cfg), 0);
    if (ret < 0) {
        OFP_LOGE("ofp_dev_set_drv_upgrade_flag 0 failed \n");
        ret = UPGRADE_FAILURE;
        goto MCU_UPGRADE_ERROR;

    }

    ret = UPGRADE_SUCCESS;



MCU_UPGRADE_ERROR:
    uapi_close_usb_handle(&(dev->usb_boot_handle));
    uapi_usb_exit();

FREE_FIRMWARE:
    free(firmware->firmware_data);
    free(firmware);
    return ret;
}




int main()
{
    int ret;
    OFP_LOGI("%s \n", OFP_UPGRADE_VERSION);

    g_ofp_dev = bio_dev_new();

    ret = ofp_dev_open_drv_config(&(g_ofp_dev->drv_cfg), OFP_DRIVER_CONFIG_FILE);
    if (ret < 0) {
        OFP_LOGE("upgrade ofp_key_file_open error \n");
        return UPGRADE_READ_CONFIG_FAILURE;
    }

    ret = ofp_dev_get_drv_config(&(g_ofp_dev->drv_cfg));
    if (ret < 0) {
        OFP_LOGE("upgrade ofp_dev_get_drv_config error \n");
        return UPGRADE_READ_CONFIG_FAILURE;
    }

    if ((g_ofp_dev->drv_cfg.upgrade_param_conf.need_upgrade_flag == 1) &&
        (g_ofp_dev->drv_cfg.device_param_conf.bus_type == USB_TYPE)) {
        ret = ofp_usb_upgrade(g_ofp_dev);
         if (ret != UPGRADE_SUCCESS) {
            OFP_LOGE("upgrade ofp_usb_upgrade error code: %d \n",ret);
            free(g_ofp_dev);
            return UPGRADE_FAILURE;
        }
    }

    ofp_dev_close_drv_config(&(g_ofp_dev->drv_cfg));
    bio_dev_free(g_ofp_dev);

    return UPGRADE_SUCCESS;
}
